﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using OF.Security.Properties;

namespace OF.Security.Utils
{
    public static class TypeCreator
    {
        private struct TypeInfo
        {
            public string AssemblyName;

            public string TypeName;

            public override string ToString()
            {
                return this.TypeName + ", " + this.AssemblyName;
            }
        }

        public static object CreateInstance(string typeDescription, params object[] constructorParams)
        {
            Type typeInfo = TypeCreator.GetTypeInfo(typeDescription);
            ExceptionHelper.FalseThrow<TypeLoadException>(typeInfo != null, Resources.TypeLoadException, new object[]
            {
                typeDescription
            });
            return TypeCreator.CreateInstance(typeInfo, constructorParams);
        }

        public static object CreateInstance(Type type, params object[] constructorParams)
        {
            ExceptionHelper.FalseThrow<ArgumentNullException>(type != null, "type", new object[0]);
            ExceptionHelper.FalseThrow<ArgumentNullException>(constructorParams != null, "constructorParams", new object[0]);
            BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;
            object result;
            if (constructorParams.Length > 0)
            {
                Type[] array = new Type[constructorParams.Length];
                for (int i = 0; i < array.Length; i++)
                {
                    array[i] = constructorParams[i].GetType();
                }
                ConstructorInfo constructor = type.GetConstructor(bindingAttr, null, CallingConventions.HasThis, array, null);
                if (constructor != null)
                {
                    result = constructor.Invoke(constructorParams);
                }
                else
                {
                    result = null;
                }
            }
            else
            {
                result = Activator.CreateInstance(type, true);
            }
            return result;
        }

        public static Type GetTypeInfo(string typeDescription)
        {
            ExceptionHelper.CheckStringIsNullOrEmpty(typeDescription, "typeDescription");
            Type type = Type.GetType(typeDescription);
            if (type == null)
            {
                TypeCreator.TypeInfo typeInfo = TypeCreator.GenerateTypeInfo(typeDescription);
                AssemblyName assemblyName = new AssemblyName(typeInfo.AssemblyName);
                AssemblyMappingConfigurationElement assemblyMappingConfigurationElement = AssemblyMappingSettings.GetConfig().Mapping[assemblyName.Name];
                ExceptionHelper.TrueThrow(assemblyMappingConfigurationElement == null, "不能找到类型{0}", new object[]
                {
                    typeDescription
                });
                typeInfo.AssemblyName = assemblyMappingConfigurationElement.MapTo;
                type = Type.GetType(typeInfo.ToString());
                ExceptionHelper.FalseThrow(type != null, "不能得到类型信息{0}", new object[]
                {
                    typeInfo.ToString()
                });
            }
            return type;
        }

        //public static object GetTypeDefaultValue(Type type)
        //{
        //    ExceptionHelper.FalseThrow<ArgumentNullException>(type != null, "type", new object[0]);
        //    object obj = null;
        //    if (type.IsValueType)
        //    {
        //        if (!TypeDefaultValueCacheQueue.Instance.TryGetValue(type, out obj))
        //        {
        //            obj = TypeCreator.CreateInstance(type, new object[0]);
        //            TypeDefaultValueCacheQueue.Instance.Add(type, obj);
        //        }
        //    }
        //    else
        //    {
        //        obj = null;
        //    }
        //    return obj;
        //}

        private static TypeCreator.TypeInfo GenerateTypeInfo(string typeDescription)
        {
            TypeCreator.TypeInfo result = default(TypeCreator.TypeInfo);
            string[] array = typeDescription.Split(new char[]
            {
                ','
            });
            result.TypeName = array[0].Trim();
            StringBuilder stringBuilder = new StringBuilder(256);
            for (int i = 1; i < array.Length; i++)
            {
                if (stringBuilder.Length > 0)
                {
                    stringBuilder.Append(", ");
                }
                stringBuilder.Append(array[i]);
            }
            result.AssemblyName = stringBuilder.ToString().Trim();
            return result;
        }


    }
}
